package edu.zhuoxun.blogserver;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.zhuoxun.blogserver.entity.Book;
import edu.zhuoxun.blogserver.entity.Category;
import edu.zhuoxun.blogserver.map.BookMapper;
import edu.zhuoxun.blogserver.map.CategoryMapper;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.net.ssl.HttpsURLConnection;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SpringBootTest
public class BooksDownload {
    @Autowired
    public CategoryMapper categoryMapper;
    @Autowired
    public BookMapper bookMapper;

    @Test
    public void readCategory() {
        Connection connect = Jsoup.connect("https://read.douban.com/category/1?sort=hot&sale=&page=1");
        try {
//            Connection.Response execute = connect.newRequest().execute();
//            System.out.println(execute.statusCode());
            Document document = connect.get();
            Elements elements = document.select("script:not([src]):eq(28)");
            String data = elements.get(0).data();
            Pattern pattern = Pattern.compile("(?<=Ark.kindTree = ).+?(?=;)");
            Matcher matcher = pattern.matcher(data);
            if (matcher.find()) {
                JSONArray array = JSON.parseArray(matcher.group());
                ((List<Object>) ((Map<String, Object>) array.get(1)).get("children")).stream()
                        .map(map -> new Category((Integer) ((Map<String, Object>) map).get("id"), (String) ((Map<String, Object>) map).get("name")))
                        .forEach(categoryMapper::insert);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void readBook() {
        String data = "{\"sort\":\"hot\",\"page\":1,\"kind\":100,\"query\":\"\\n    query getFilterWorksList($works_ids: [ID!]) {\\n      worksList(worksIds: $works_ids) {\\n        \\n    \\n  title\\n  cover\\n  url\\n  isBundle\\n  coverLabel\\n\\n    \\n  url\\n  title\\n\\n    \\n  author {\\n    name\\n    url\\n  }\\n  origAuthor {\\n    name\\n    url\\n  }\\n  translator {\\n    name\\n    url\\n  }\\n\\n    \\n  abstract\\n  authorHighlight\\n  editorHighlight\\n\\n    \\n    isOrigin\\n    kinds {\\n      \\n    name @skip(if: true)\\n    shortName @include(if: true)\\n    id\\n  \\n    }\\n    ... on WorksBase @include(if: true) {\\n      wordCount\\n      wordCountUnit\\n    }\\n    ... on WorksBase @include(if: false) {\\n      inLibraryCount\\n    }\\n    ... on WorksBase @include(if: false) {\\n      \\n    isEssay\\n    \\n    ... on EssayWorks {\\n      favorCount\\n    }\\n  \\n    \\n    \\n    averageRating\\n    ratingCount\\n    url\\n  \\n  \\n  \\n    }\\n    ... on WorksBase @include(if: false) {\\n      isColumn\\n      isEssay\\n      onSaleTime\\n      ... on ColumnWorks {\\n        updateTime\\n      }\\n    }\\n    ... on WorksBase @include(if: true) {\\n      isColumn\\n      ... on ColumnWorks {\\n        isFinished\\n      }\\n    }\\n    ... on EssayWorks {\\n      essayActivityData {\\n        \\n    title\\n    uri\\n    tag {\\n      name\\n      color\\n      background\\n      icon2x\\n      icon3x\\n      iconSize {\\n        height\\n      }\\n      iconPosition {\\n        x y\\n      }\\n    }\\n  \\n      }\\n    }\\n    highlightTags {\\n      name\\n    }\\n  \\n    \\n  ... on WorksBase {\\n    copyrightInfo {\\n      newlyAdapted\\n      newlyPublished\\n      adaptedName\\n      publishedName\\n    }\\n  }\\n\\n    isInLibrary\\n    ... on WorksBase @include(if: false) {\\n      \\n    fixedPrice\\n    salesPrice\\n    isRebate\\n  \\n    }\\n    ... on EbookWorks {\\n      \\n    fixedPrice\\n    salesPrice\\n    isRebate\\n  \\n    }\\n    ... on WorksBase @include(if: true) {\\n      ... on EbookWorks {\\n        id\\n        isPurchased\\n        isInWishlist\\n      }\\n    }\\n  \\n        id\\n        isOrigin\\n      }\\n    }\\n  \",\"variables\":{}}";
        Map<String, Object> map = new HashMap<>();
        map.put("sort", "rating");
        map.put("page", 1);
        map.put("query","\n" +
                "    query getFilterWorksList($works_ids: [ID!]) {\n" +
                "      worksList(worksIds: $works_ids) {\n" +
                "        \n" +
                "    \n" +
                "  title\n" +
                "  cover\n" +
                "  url\n" +
                "  isBundle\n" +
                "  coverLabel\n" +
                "\n" +
                "    \n" +
                "  url\n" +
                "  title\n" +
                "\n" +
                "    \n" +
                "  author {\n" +
                "    name\n" +
                "    url\n" +
                "  }\n" +
                "  origAuthor {\n" +
                "    name\n" +
                "    url\n" +
                "  }\n" +
                "  translator {\n" +
                "    name\n" +
                "    url\n" +
                "  }\n" +
                "\n" +
                "    \n" +
                "  abstract\n" +
                "  authorHighlight\n" +
                "  editorHighlight\n" +
                "\n" +
                "    \n" +
                "    isOrigin\n" +
                "    kinds {\n" +
                "      \n" +
                "    name @skip(if: true)\n" +
                "    shortName @include(if: true)\n" +
                "    id\n" +
                "  \n" +
                "    }\n" +
                "    ... on WorksBase @include(if: true) {\n" +
                "      wordCount\n" +
                "      wordCountUnit\n" +
                "    }\n" +
                "    ... on WorksBase @include(if: false) {\n" +
                "      inLibraryCount\n" +
                "    }\n" +
                "    ... on WorksBase @include(if: false) {\n" +
                "      \n" +
                "    isEssay\n" +
                "    \n" +
                "    ... on EssayWorks {\n" +
                "      favorCount\n" +
                "    }\n" +
                "  \n" +
                "    \n" +
                "    \n" +
                "    averageRating\n" +
                "    ratingCount\n" +
                "    url\n" +
                "  \n" +
                "  \n" +
                "  \n" +
                "    }\n" +
                "    ... on WorksBase @include(if: false) {\n" +
                "      isColumn\n" +
                "      isEssay\n" +
                "      onSaleTime\n" +
                "      ... on ColumnWorks {\n" +
                "        updateTime\n" +
                "      }\n" +
                "    }\n" +
                "    ... on WorksBase @include(if: true) {\n" +
                "      isColumn\n" +
                "      ... on ColumnWorks {\n" +
                "        isFinished\n" +
                "      }\n" +
                "    }\n" +
                "    ... on EssayWorks {\n" +
                "      essayActivityData {\n" +
                "        \n" +
                "    title\n" +
                "    uri\n" +
                "    tag {\n" +
                "      name\n" +
                "      color\n" +
                "      background\n" +
                "      icon2x\n" +
                "      icon3x\n" +
                "      iconSize {\n" +
                "        height\n" +
                "      }\n" +
                "      iconPosition {\n" +
                "        x y\n" +
                "      }\n" +
                "    }\n" +
                "  \n" +
                "      }\n" +
                "    }\n" +
                "    highlightTags {\n" +
                "      name\n" +
                "    }\n" +
                "  \n" +
                "    \n" +
                "  ... on WorksBase {\n" +
                "    copyrightInfo {\n" +
                "      newlyAdapted\n" +
                "      newlyPublished\n" +
                "      adaptedName\n" +
                "      publishedName\n" +
                "    }\n" +
                "  }\n" +
                "\n" +
                "    isInLibrary\n" +
                "    ... on WorksBase @include(if: false) {\n" +
                "      \n" +
                "    fixedPrice\n" +
                "    salesPrice\n" +
                "    isRebate\n" +
                "  \n" +
                "    }\n" +
                "    ... on EbookWorks {\n" +
                "      \n" +
                "    fixedPrice\n" +
                "    salesPrice\n" +
                "    isRebate\n" +
                "  \n" +
                "    }\n" +
                "    ... on WorksBase @include(if: true) {\n" +
                "      ... on EbookWorks {\n" +
                "        id\n" +
                "        isPurchased\n" +
                "        isInWishlist\n" +
                "      }\n" +
                "    }\n" +
                "  \n" +
                "        id\n" +
                "        isOrigin\n" +
                "      }\n" +
                "    }\n" +
                "  ");
        map.put("variables", new JSONObject());
        map.put("kind", 100);
        System.out.println(JSON.toJSONString(map));
        List<Category> categories = categoryMapper.selectList(new QueryWrapper<Category>());
        categories.forEach(c -> {
            for (int i = 1; i <= 10; i++) {

                try {
                    HttpsURLConnection connection = (HttpsURLConnection) new URL("https://read.douban.com/j/kind/").openConnection();
                    connection.setRequestMethod("POST");
                    connection.setDoOutput(true);
                    connection.setRequestProperty("content-type", "application/json");
                    connection.setRequestProperty("Referer", "https://read.douban.com/category/100?sort=rating&kind=1");
                    connection.setRequestProperty("User-Agent", "");

                    OutputStream os = connection.getOutputStream();
                    map.put("page", i);
                    map.put("kind", c.getId());

                    os.write(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
                    os.flush();
                    os.close();
                    InputStream is = connection.getInputStream();
                    byte[] buffer = new byte[102400];
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    int length;
                    while ((length = is.read(buffer)) != -1) {
                        bos.write(buffer, 0, length);
                    }
                    JSONObject object = JSON.parseObject(bos.toString(StandardCharsets.UTF_8));
                    System.out.println(object.getInteger("total"));
                    JSONArray list = object.getJSONArray("list");
                    for (int i1 = 0; i1 < list.size(); i1++) {
                        JSONObject jbook = list.getJSONObject(i1);
                        Book book = new Book();
                        book.setId(jbook.getInteger("id"));
                        book.setCover(jbook.getString("cover"));
                        book.setAbs(jbook.getString("abstract"));
                        book.setTitle(jbook.getString("title"));
                        JSONArray author = jbook.getJSONArray("author");
                        if (author.isEmpty()) {
                            author = jbook.getJSONArray("origAuthor");
                        }
                        book.setAuthor(author.getJSONObject(0).getString("name"));
                        book.setCId(c.getId());
//                        System.out.println(book);
                        try {
                            bookMapper.insert(book);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
